﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using UDIServer;
using UDITest;
using Clipboard = System.Windows.Forms.Clipboard;

namespace ScanUDI
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private SolidColorBrush connColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#16baaa"));
        private SolidColorBrush disConnColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#ff5722"));
        private SolidColorBrush msgColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#ffb800"));
        private ManagementEventWatcher watcher;

        SerialTool _serialTool = new SerialTool();

        readonly string VID = "0x0525";
        readonly string PID = "0xA4A7";

        public MainWindow()
        {
            // 监听设备插入和移除的事件
            var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 or EventType = 3");
            watcher = new ManagementEventWatcher(query);
            watcher.EventArrived += Watcher_EventArrived; ;
            watcher.Start();

            double margin = 50;
            this.Topmost = true;
            this.Left = SystemParameters.PrimaryScreenWidth - margin - 100;
            this.Top = margin;
            InitializeComponent();
            this.mainBorder.Background = disConnColor;
            //MouseDown += (s, e) =>
            //{
            //    ShowMsg("拖动窗口");
            //};

            MouseDoubleClick += (s, e) =>
            {
                //关闭释放所有资源
                _serialTool.Close();
                this.Close();
            };

            Watcher_EventArrived(null, null);
        }


        private bool _isConn;
        private void ChangeStatus(bool isConn)
        {
            _isConn = isConn;   
            if (isConn)
            {
                Dispatcher.Invoke(() =>
                {
                    this.mainBorder.Background = connColor;
                    this.txtInfo.Text = "已连接";
                });
            }
            else
            {
                _serialTool.Close();
                Dispatcher.Invoke(() =>
                {
                    this.mainBorder.Background = disConnColor;
                    this.txtInfo.Text = "未连接";

                });
            }
        }

        UDICode udi;
        static int waitTime = 0;

        private void ShowMsg(string msg)
        {
            waitTime = 3;
            Dispatcher.Invoke(() =>
            {
                txtInfo.Text = msg;
                mainBorder.Background = msgColor;
                Task.Run(() =>
                {
                    while (waitTime > 0)
                    {
                        Thread.Sleep(1000);
                        waitTime--;
                    }
                    ChangeStatus(_isConn);
                });
            });
        }

        static object locker = new object();
        int inn = 0;

        /// <summary>
        /// 设备插入或拔出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Watcher_EventArrived(object sender, EventArrivedEventArgs e)
        {
            Task.Run(() =>
            {
                lock (locker)
                {
                    if (inn >= 1)
                    {
                        return;
                    } 
                    inn++;
                    try
                    {
                        var isHave = _serialTool.Open(VID, PID, data =>
                          {
                              udi = new UDICode();
                              CheckUDI(data);
                          });
                    }
                    catch (Exception ex)
                    {
                           
                    }
                    finally
                    {
                        ChangeStatus(_serialTool.CheckConn());
                    }
                    inn = 0;
                }
            });
        }

        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //移动窗口
            this.DragMove();
        }

        private void CheckUDI(string code)
        {
            udi.Code = code.Trim();
            if (!Regex.IsMatch(udi.Code, "^[a-zA-Z0-9]+$"))
            {
                ShowMsg("非UDI码");
                return;
            }
            AnalysisUDI(udi, udi.Code);
            SendUDI();
        }

        /// <summary>
        /// 递归解析UDI码
        /// </summary>
        /// <param name="udi"></param>
        /// <param name="code"></param>
        private void AnalysisUDI(UDICode udi, string code)
        {
            if (string.IsNullOrEmpty(code)) return; // 没有可以解析的 直接return
            string nextCode;
            if (code.StartsWith("01"))
            {
                if (code.Length <= 16)
                {
                    udi.Di = code.Substring(2);
                    return;
                }
                else
                {
                    udi.Di = code.Substring(2, 14);
                    nextCode = code.Substring(2 + udi.Di.Length);
                    AnalysisUDI(udi, nextCode);
                }
            }

            if (code.StartsWith("10"))
            {
                udi.BatchNumber = code.Substring(2);
                return;
            }

            if (code.StartsWith("11"))
            {
                udi.ProductionDate = code.Substring(2, 6);
                nextCode = code.Substring(8);
                AnalysisUDI(udi, nextCode);
            }

            if (code.StartsWith("17"))
            {
                udi.ExpirationDate = code.Substring(2, 6);
                nextCode = code.Substring(8);
                AnalysisUDI(udi, nextCode);
            }

            if (code.StartsWith("21"))
            {
                udi.SerialNumber = code.Substring(2);
            }
        }

        private void SendUDI()
        {
            if (
                   string.IsNullOrEmpty(udi.ExpirationDate) &&
                   string.IsNullOrEmpty(udi.ProductionDate))
            {
                ShowMsg("无效UDI");

            }
            else
            {
                Dispatcher.Invoke(() =>
                {
                    var sendMsg = $"{udi.Di},{udi.BatchNumber},{udi.ProductionDate},{udi.ExpirationDate},{udi.SerialNumber}";
                    
                    //JsonConvert.SerializeObject(new List<UDICode> { udi });

                    // 将字符串复制到剪贴板
                    Clipboard.SetText(sendMsg);

                    PressKey(Keys.ControlKey, false);
                    PressKey(Keys.V, false);
                    PressKey(Keys.V, true);
                    PressKey(Keys.ControlKey, true);
                    PressKey(Keys.Enter, false);
                    PressKey(Keys.Enter, true);
                });
            }
        }

        #region 系统复制 粘贴相关
        [DllImport("user32.dll", SetLastError = true)]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
        public static void PressKey(Keys key, bool up)
        {
            const int KEYEVENTF_EXTENDEDKEY = 0x1;
            const int KEYEVENTF_KEYUP = 0x2;
            if (up)
            {

                keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);

            }
            else
            {

                keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);

            }
        }
        #endregion
    }
}
